package com.zj.cglib;

import com.zj.service.Actor;
import net.sf.cglib.proxy.*;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Method;

public class StarEnhancer implements MethodInterceptor {

    private Class<?> tClass;//jdk代理必须要目标对象来做反射，cglib不用对象只需要目标类

    private Actor actor=new Actor();
    public StarEnhancer(Class<?> c){
        this.tClass=c;
    }

    @Override
    //代理类的CGLIB$sing$1(String var1)方法就是super.sing(var1)直接调用父类的方法。
    //代理类的sing方法是调用增强器MethodInterceptor的intercept方法。
    // (String)var10000.intercept(this, CGLIB$sing$1$Method, new Object[]{var1}, CGLIB$sing$1$Proxy) : super.sing(var1);
    //在代理类中，obj是代理对象，不是目标对象，所以不能用method.invoke(obj,args),这样就会再次进入代理类的sing方法形成死循环。
    //methodProxy上面代理类的CGLIB$sing$1(String var1)方法，因此需要传入代理对象obj和参数args
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before method: " + obj.getClass()); // 方法调用前的操作
        //如果StarEnhancer中保存了目标类target，倒是可以用method.invoke(target,args);
        //但是cglib的独特性就是在这里用了fastclass机制，这里的methodProxy不是CGLIB$sing$1，是一个封装类
        //通过fastclass最后调用CGLIB$sing$1(String var1)
        Object result = methodProxy.invokeSuper(obj, args); //目标类内部之间方法调用也会对嵌套方法进行增强
        //Object result = methodProxy.invokeSuper(actor, args);//会报错，目标类actor不能转换为代理类
        //Object result = methodProxy.invoke(actor, args);//内部之间方法调用不会对嵌套方法进行增强

        //Object result = method.invoke(actor, args);//通过反射调用目标类方法
        //Object result = method.invoke(obj, args);//会陷入死循环，代理对象又调用了sing方法
        //Object result = methodProxy.invoke(obj, args);//会陷入死循环，代理对象又调用了sing方法
        System.out.println("After method: " + method.getName()); // 方法调用后的操作
        return result; // 返回结果
    }
    public Object CreatProxyedObj()    {
        Enhancer enhancer=new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(tClass);
        return enhancer.create();
    }
//通过objene生成代理类略有不同，会绕过父类构造直接产生子类
    public Object CreatProxyedObj2() {
        Enhancer enhancer=new Enhancer();
        enhancer.setCallbackType(this.getClass());
        enhancer.setSuperclass(tClass);
        Class aClass = enhancer.createClass();
        Enhancer.registerCallbacks(aClass,new Callback[]{this});
        enhancer.setInterceptDuringConstruction(false);
        ObjenesisStd std = new ObjenesisStd(true);
        return std.newInstance(aClass);
    }
//设置callbackfilter的方式,这里用来代理类中有多个方法，每个方法指定不同代理策略的情况。
    public Object CreatProxyedObj3() {
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(tClass);
        enhancer.setCallbackFilter(new CallbackFilter(){
            public int accept(Method method) {
                if("sing".equals(method.getName())){
                    return 0;//Callback callbacks[0]
                }else if("dance".equals(method.getName())){
                    return 1;//Callback callbacks[1]
                }else if("eat".equals(method.getName())){
                    return 2;//Callback callbacks[2]
                }
                return 1;
        }});
        Callback[] callbacks=new Callback[]{this,NoOp.INSTANCE,new FixedValue() {
            @Override
            public Object loadObject() throws Exception {
                System.out.println("fixvalue");
                return 1;
            }
        }};
        enhancer.setCallbacks(callbacks);
        return enhancer.create();
    }
}
